package com.victor9ac.tfm.web.controller;


import java.util.concurrent.Future;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.victor9ac.tfm.mashup.connector.exception.MashupConnectionException;
import com.victor9ac.tfm.mashup.connector.port.MashupConnector;
import com.victor9ac.tfm.web.exception.MashupTimeoutException;
import com.victor9ac.tfm.web.exception.MashupNoContentException;
import com.victor9ac.tfm.web.model.comment.CommentariesView;
import com.victor9ac.tfm.web.model.photos.PhotosView;
import com.victor9ac.tfm.web.model.travel.TravelView;
import com.victor9ac.tfm.web.threadpool.MashupThreadPool;

@Component
@Controller
@RequestMapping("/web")
public class MashupWebController {
	private static final String TIMEOUT_PAGE = "timeout";
	private static final String NOCONTENT_PAGE = "noContent";
	private static final String SUCESSFUL_PAGE = "mashup";

	@Autowired
	private MashupConnector commentsConnector;
	@Autowired
	private MashupConnector imagesConnector;
	
	@Autowired
	private MashupConnector travelConnector;
	
	@Autowired
	private MashupThreadPool mashupThreadPool;
	
	@Autowired
	private HttpServletRequest request;

	@RequestMapping(value = "/{name}", method = RequestMethod.GET)
	@ResponseStatus(HttpStatus.OK)
	public String getOnePlace(@PathVariable String name, ModelMap model)
			throws MashupNoContentException,MashupConnectionException,MashupTimeoutException {

		long ini = System.currentTimeMillis();


		// launch threads
		Future<CommentariesView> commentFuture = mashupThreadPool.invoke(
				commentsConnector, name, CommentariesView.class);
		
		Future<PhotosView> photoFuture = mashupThreadPool.invoke(
				imagesConnector, name, PhotosView.class);
		
		Future<TravelView> travelFuture = mashupThreadPool.invoke(travelConnector, buildQueryBasedOnIp(name), TravelView.class);

		// collect thread resutls
		CommentariesView commentView = mashupThreadPool
				.getResult(commentFuture);
		
		PhotosView photosView = mashupThreadPool.getResult(photoFuture);
		
		TravelView travelView = mashupThreadPool.getResult(travelFuture);
		

		
		System.out.println("travel?  "+ travelView!=null);
		System.out.println("total time: " + (System.currentTimeMillis() - ini));
		model.addAttribute("keyword", name);
		
		checkResults(commentView, photosView);
		buildModel(model, commentView, photosView,travelView);

		return SUCESSFUL_PAGE;
	}



	private String buildQueryBasedOnIp(String name) {
		System.out.println("remote addr: "+request.getRemoteAddr());
		return request.getRemoteAddr()+"/"+name;
	}



	@ExceptionHandler(MashupNoContentException.class)
	@ResponseStatus(HttpStatus.NOT_FOUND)
	public String noContentHandler() {
		return NOCONTENT_PAGE;
	}

	@ExceptionHandler(MashupTimeoutException.class)
	@ResponseStatus(HttpStatus.REQUEST_TIMEOUT)
	public String requestTimeoutHandler() {

		return TIMEOUT_PAGE;
	}
	
	
	@ExceptionHandler(MashupConnectionException.class)
	@ResponseStatus(HttpStatus.REQUEST_TIMEOUT)
	public String connectionHandler() {

		return TIMEOUT_PAGE;
	}
	

	private void buildModel(ModelMap model, CommentariesView commentView,
			PhotosView photosView,TravelView travelView) {
		model.addAttribute(commentView);
		model.addAttribute(photosView);
		model.addAttribute(travelView);
	}

	private void checkResults(CommentariesView commentView,
			PhotosView photosView) throws MashupNoContentException {
		if (!hasAllContent(commentView, photosView)) {
			throw new MashupNoContentException();
		}
	}
	
	private boolean hasAllContent(CommentariesView commentView,
			PhotosView photosView) {
		return commentView != null && photosView != null;
	}

	
	// setters
	public void setCommentsConnector(MashupConnector commentsConnector) {
		this.commentsConnector = commentsConnector;
	}

	public void setImagesConnector(MashupConnector imagesConnector) {
		this.imagesConnector = imagesConnector;
	}

	public void setMashupThreadPool(MashupThreadPool mashupThreadPool) {
		this.mashupThreadPool = mashupThreadPool;
	}

}